using System;
using System.Linq;
using NLite.Mini.Context;
using System.Collections.Generic;
using System.Runtime.Remoting.Messaging;
using System.Text;
using NLite.Internal;

namespace NLite.Mini.Activation
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public abstract class AbstractActivator : MarshalDisposable, IActivator
    {
        private readonly object SyncRoot = new object();
        private bool hasLock;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public virtual object Create(IPreCreationContext context)
        {
            Tracker.Track(context);

            if (hasLock)
                throw new LoopDependencyException(Tracker.CallStack);

            object instance = null;

            lock (SyncRoot)
            {
                hasLock = true;

                var componentListner = context.Kernel.ListenerManager as IComponentListener;

                if (componentListner != null)
                    componentListner.OnPreCreation(context);
               
                //Create instance
                instance = InternalCreate(context);

                if (componentListner != null)
                {
                    var postCreateContext = new PostCreationContext(context.Kernel, context.Component, instance);
                    componentListner.OnPostCreation(postCreateContext);
                    componentListner.OnInitialization(postCreateContext);
                    componentListner.OnPostInitialization(postCreateContext);
                }

                Tracker.Clear();
            }

            hasLock = false;

            return instance;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        protected virtual object InternalCreate(IPreCreationContext context) { throw new NotImplementedException(); }

       
    }
}
